/**
 * Copyright 厦门中软海晟信息技术有限公司 版权所有 违者必究 2019
 */
package com.opencvjava.lessons.imgproc;

import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.springframework.stereotype.Service;

import static com.opencvjava.support.util.CommonUtils.cost;
import static com.opencvjava.support.util.CvUtils.imshow;
import static com.opencvjava.support.util.CvUtils.mat;
import static org.opencv.imgproc.Imgproc.*;
import static org.opencv.imgcodecs.Imgcodecs.*;
import static org.opencv.core.Core.*;

/**
 * @author : sunzb(sunzb@hsit.com.cn)
 * @date: 2019/1/4
 */
@Service
public class L3_SmoothingImages {
    private static final int DELAY_CAPTION = 1500;
    private static final int DELAY_BLUR = 100;
    private static final int MAX_KERNEL_LENGTH = 11;
    private final String windowName = "Filter Demo 1";
    private Mat src;
    private Mat dst;

    public void test() {
        src = mat("lena.jpg");
        if (src.empty()) {
            throw new RuntimeException("读取图片失败");
        }
        displayCaption("Original Image");
        dst = src.clone();
        displayDst(DELAY_CAPTION);
        displayCaption("Homogeneous Blur");
        for (int i = 3; i < MAX_KERNEL_LENGTH; i = i + 2) {
            blur(src, dst, new Size(i, i), new Point(-1, -1));
            displayDst(DELAY_BLUR);
        }
        displayCaption("Gaussian Blur");
        for (int i = 3; i < MAX_KERNEL_LENGTH; i = i + 2) {
            GaussianBlur(src, dst, new Size(i, i), 0, 0);
            displayDst(DELAY_BLUR);
        }
        displayCaption("Median Blur");
        for (int i = 3; i < MAX_KERNEL_LENGTH; i = i + 2) {
            medianBlur(src, dst, i);
            displayDst(DELAY_BLUR);
        }
        displayCaption("Bilateral Blur");
        for (int i = 3; i < MAX_KERNEL_LENGTH; i = i + 2) {
            // 双边滤波其实是高斯滤波，除了空间距离的高斯分布，多了颜色差异的高斯分布
            // 第三个参数经常是0
            bilateralFilter(src, dst, i, i * 2, i / 2);
            displayDst(DELAY_BLUR);
        }
        displayCaption("Done!");
        // more 展示双边滤波的神奇威力
        Mat image = mat("bilateral.png");
        imshow("双边滤波美颜之前", image);
        Mat result = new Mat();
        long start = System.nanoTime();
        bilateralFilter(image, result, 25, 80, 5);
        cost("双边滤波", start);
        imshow("双边滤波美颜之后", result);
    }

    private void displayCaption(String caption) {
        dst = Mat.zeros(src.size(), src.type());
        putText(dst, caption,
                new Point(src.cols() / 4, src.rows() / 2),
                FONT_HERSHEY_COMPLEX, 1, new Scalar(255, 255, 255));
        displayDst(DELAY_CAPTION);
    }

    private void displayDst(int delay) {
        imshow(windowName, dst);
        try {
            Thread.sleep(delay);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }
}
